package com.lucifer.treasure;

import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.minecraft.client.MinecraftClient;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;

public class MultiJumpClientHandler implements ClientModInitializer {
    
    private boolean wasJumpPressed = false;
    private int jumpsUsed = 0;
    private boolean wasOnGround = true;
    private int airTicks = 0;
    private long lastJumpTime = 0;
    
    // Configuration constants
    private static final int MIN_AIR_TIME = 8; // Minimum air time before jumping
    private static final int JUMP_COOLDOWN = 200; // Jump interval cooldown (ms)
    private static final float JUMP_POWER = 0.8f; // Jump strength
    
    @Override
    public void onInitializeClient() {
        // Register client tick event to detect jump key
        ClientTickEvents.END_CLIENT_TICK.register(client -> {
            if (client.player != null && client.world != null) {
                handleJumpInput(client);
            }
        });
    }
    
    /**
     * Handle jump input detection
     */
    private void handleJumpInput(MinecraftClient client) {
        PlayerEntity player = client.player;
        if (player == null) return;
        
        boolean jumpPressed = client.options.jumpKey.isPressed();
        boolean sneaking = client.options.sneakKey.isPressed();
        boolean isOnGround = player.isOnGround();
        
        // Update air time and ground state
        if (isOnGround) {
            if (!wasOnGround) {
                // Just landed, reset jump count
                jumpsUsed = 0;
            }
            airTicks = 0;
        } else {
            airTicks++;
        }
        wasOnGround = isOnGround;
        
        // Detect jump key press (state change from not pressed to pressed)
        if (jumpPressed && !wasJumpPressed) {
            // Sneaking cancels multi-jump functionality
            if (sneaking) {
                // No multi-jump when sneaking
                wasJumpPressed = jumpPressed;
                return;
            }
            
            // Check if multi-jump can be performed
            if (canPerformMultiJump(player)) {
                performMultiJump(player);
            }
        }
        
        wasJumpPressed = jumpPressed;
    }
    
    /**
     * Check if multi-jump can be performed
     */
    private boolean canPerformMultiJump(PlayerEntity player) {
        // Basic condition checks
        if (player.isOnGround() || 
            player.isTouchingWater() || 
            player.hasVehicle() ||
            player.getAbilities().flying ||
            player.isSpectator()) {
            return false;
        }
        
        // Check if falling
        if (player.getVelocity().y >= 0) {
            return false;
        }
        
        // Check air time
        if (airTicks < MIN_AIR_TIME) {
            return false;
        }
        
        // Check cooldown time
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastJumpTime < JUMP_COOLDOWN) {
            return false;
        }
        
        // Get multi-jump level
        int multiJumpLevel = getMultiJumpLevel(player);
        if (multiJumpLevel <= 0) {
            return false;
        }
        
        // Check jump count: each level adds one jump
        if (jumpsUsed >= multiJumpLevel) {
            return false;
        }
        
        return true;
    }
    
    /**
     * Perform multi-jump
     */
    private void performMultiJump(PlayerEntity player) {
        // Set upward velocity
        player.setVelocity(player.getVelocity().x, JUMP_POWER, player.getVelocity().z);
        player.fallDistance = 0;
        
        // Increase used jump count
        jumpsUsed++;
        lastJumpTime = System.currentTimeMillis();
        
        // Play sound effect
        player.getWorld().playSound(player, player.getX(), player.getY(), player.getZ(),
                SoundEvents.ENTITY_ENDER_DRAGON_FLAP, SoundCategory.PLAYERS,
                0.5f, 1.0f + (jumpsUsed * 0.1f)); // Pitch increases with jump count
        
        // Generate particle effects
        if (player.getWorld().isClient) {
            // Cloud particles (云朵粒子)
            for (int i = 0; i < 12; i++) {
                double offsetX = (player.getRandom().nextDouble() - 0.5) * 1.0;
                double offsetZ = (player.getRandom().nextDouble() - 0.5) * 1.0;
                player.getWorld().addParticle(ParticleTypes.CLOUD,
                        player.getX() + offsetX, player.getY() + 0.1, player.getZ() + offsetZ,
                        0, 0.02, 0);
            }
            
            // White explosion particles (白色爆炸粒子)
            for (int i = 0; i < 8; i++) {
                double offsetX = (player.getRandom().nextDouble() - 0.5) * 0.8;
                double offsetZ = (player.getRandom().nextDouble() - 0.5) * 0.8;
                player.getWorld().addParticle(ParticleTypes.POOF,
                        player.getX() + offsetX, player.getY() + 0.2, player.getZ() + offsetZ,
                        0, 0.05, 0);
            }
            
            // Add portal particles for high-level jumps (3级以上传送门粒子)
            if (jumpsUsed >= 3) {
                for (int i = 0; i < 5; i++) {
                    double offsetX = (player.getRandom().nextDouble() - 0.5) * 0.8;
                    double offsetY = player.getRandom().nextDouble() * 0.5;
                    double offsetZ = (player.getRandom().nextDouble() - 0.5) * 0.8;
                    player.getWorld().addParticle(ParticleTypes.PORTAL,
                            player.getX() + offsetX, player.getY() + offsetY, player.getZ() + offsetZ,
                            0, -0.1, 0);
                }
            }
        }
    }
    
    /**
     * Get player's multi-jump level
     */
    private int getMultiJumpLevel(PlayerEntity player) {
        int maxLevel = 0;
        
        // Check boots
        for (ItemStack armorStack : player.getArmorItems()) {
            if (!armorStack.isEmpty()) {
                int level = getMultiJumpLevelFromStack(armorStack);
                maxLevel = Math.max(maxLevel, level);
            }
        }
        
        // Check elytra (in chest slot)
        ItemStack chestItem = player.getInventory().getArmorStack(2); // Chest slot
        if (chestItem.getItem() == Items.ELYTRA) {
            int level = getMultiJumpLevelFromStack(chestItem);
            maxLevel = Math.max(maxLevel, level);
        }
        
        return maxLevel;
    }
    
    /**
     * Get MultiJump enchantment level from item stack
     */
    private int getMultiJumpLevelFromStack(ItemStack stack) {
        if (stack.isEmpty()) {
            return 0;
        }
        
        var enchantments = EnchantmentHelper.getEnchantments(stack);
        return enchantments.getEnchantments().stream()
                .filter(entry -> {
                    if (entry.getKey().isPresent()) {
                        return entry.getKey().get().getValue().toString().equals("lucifer_treasure:multijump");
                    }
                    return false;
                })
                .mapToInt(entry -> enchantments.getLevel(entry))
                .max()
                .orElse(0);
    }
}
